package com.sts.source.impl;

import com.sts.source.StsSource;
import com.sts.source.model.CsvSourceConfig;
import de.siegmar.fastcsv.reader.CsvReader;
import de.siegmar.fastcsv.reader.CsvRecord;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Stream;

@Slf4j
public class CsvSourceImpl implements StsSource {

    private CsvReader<CsvRecord> csvReader;
    private final CsvSourceConfig csvSourceConfig;

    public CsvSourceImpl(CsvSourceConfig csvSourceConfig) {
        this.csvSourceConfig = csvSourceConfig;
    }

    @Override
    public List<String> getHeader() {
        if (!csvSourceConfig.isHasHeader()) {
            // false: 文件没有头，用指定的头
            return csvSourceConfig.getHeaderList();
        }

        try (CsvReader<CsvRecord> csvReader = buildCsvReader()) {
            return csvReader.stream()
                    .findFirst()
                    .orElseThrow(() -> new RuntimeException("csv文件为空"))
                    .getFields();
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    @Override
    public Stream<List<String>> getDataStream() {
        csvReader = buildCsvReader();

        Stream<CsvRecord> stream = csvReader.stream();
        if (csvSourceConfig.isHasHeader()) {
            // true: 文件有头，需要跳过第一行头数据
            stream = stream.skip(1);
        }
        return stream.map(CsvRecord::getFields);
    }

    @Override
    public void close() throws Exception {
        if (csvReader != null) {
            csvReader.close();
            log.info("CsvReader Closed");
        }
    }

    private CsvReader<CsvRecord> buildCsvReader() {
        try {
            return CsvReader.builder()
                    .fieldSeparator(csvSourceConfig.getFieldSeparator())
                    .quoteCharacter(csvSourceConfig.getQuoteCharacter())
                    .skipEmptyLines(csvSourceConfig.isSkipEmptyLines())
                    .detectBomHeader(csvSourceConfig.isDetectBomHeader())
                    .ofCsvRecord(Paths.get(csvSourceConfig.getFilePath()));
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

}
